package com.java.springcloud.mybatisplus.injector.methods;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import com.java.springcloud.mybatisplus.annotation.TableTag;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

import java.lang.reflect.Field;
import java.util.List;
import java.util.StringJoiner;

/**
 * 插入一条数据（选择字段插入）
 *
 * @author zhangtao
 * @since 2018-04-06
 */
public class TdInsert extends AbstractMethod {

    private static final String TD_INSERT = "<script>\nINSERT INTO %s %s VALUES %s\n</script>";
    private static final String USING = "%s USING %s %s TAGS %s";

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE;
        String columnScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlColumnMaybeIf(),
                LEFT_BRACKET, RIGHT_BRACKET, null, COMMA);
        String valuesScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlPropertyMaybeIf(null),
                LEFT_BRACKET, RIGHT_BRACKET, null, COMMA);

        String usingScript = tableInfo.getTableName();

        List<Field> fieldList = ReflectionKit.getFieldList(ClassUtils.getUserClass(modelClass));
        StringJoiner columnJoiner = new StringJoiner(NEWLINE);
        StringJoiner propertyJoiner = new StringJoiner(NEWLINE);
        StringJoiner tableNameJoiner = new StringJoiner("");
        tableNameJoiner.add(tableInfo.getTableName());
        fieldList.stream()
                .forEach(field -> {
                    TableTag tableTag = field.getAnnotation(TableTag.class);
                    if (tableTag != null) {
                        String column = SqlScriptUtils.convertIf(tableTag.value() + COMMA, String.format("%s != null", field.getName()), false);
                        String property = SqlScriptUtils.convertIf(SqlScriptUtils.safeParam(field.getName()) + COMMA, String.format("%s != null", field.getName()), false);
                        String tag = SqlScriptUtils.convertIf(UNDERSCORE + SqlScriptUtils.unSafeParam(field.getName()), String.format("%s != null", field.getName()), false);
                        columnJoiner.add(column);
                        propertyJoiner.add(property);
                        tableNameJoiner.add(tag);
                    }
                });

        if (columnJoiner.length() != 0) {
            String usingColumnScript = SqlScriptUtils.convertTrim(columnJoiner.toString(),
                    LEFT_BRACKET, RIGHT_BRACKET, null, COMMA);

            String usingPropertyScript = SqlScriptUtils.convertTrim(propertyJoiner.toString(),
                    LEFT_BRACKET, RIGHT_BRACKET, null, COMMA);

            String newTableName = SqlScriptUtils.convertTrim(tableNameJoiner.toString(),
                    "", "", null, null);

            usingScript = String.format(USING, newTableName, tableInfo.getTableName(), usingColumnScript, usingPropertyScript);
        }
        String sql = String.format(TD_INSERT, usingScript, columnScript, valuesScript);
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return this.addInsertMappedStatement(mapperClass, modelClass, "tdInsert", sqlSource, keyGenerator, null, null);
    }

}
